Skip to content

ci: publish releases from pre-built CI artifacts - #5626

Open
deadprogram wants to merge 1 commit into
devfrom
ci-release-workflow
Open

ci: publish releases from pre-built CI artifacts#5626
deadprogram wants to merge 1 commit into
devfrom
ci-release-workflow

Conversation

@deadprogram

@deadprogram deadprogram commented Aug 29, 2026

Copy link
Copy Markdown
Member

This PR is to improve the release process.

CI already builds every file that a release needs. Only the publication is
manual: download nine artifacts from three runs, create the release, attach the
files, paste the CHANGELOG entry.

This adds a Release workflow that does that work. It builds nothing. The
Linux, macOS and Windows workflows already run on the release branch push, so
the workflow finds those runs for the tagged commit, waits for them, and
collects their artifacts. What ships is what was tested, and no existing
workflow changes.

Trigger. A v* tag push starts it. workflow_dispatch with a tag input
allows a second attempt without a move of the tag.

Checks.

  • The tag must be v plus the version in goenv/version.go, because the file
    names come from that constant. A -dev version stops the release.
  • Each of the three runs must conclude successfully. A tagged commit that CI
    never built stops the release.
  • All nine files must be present. A build that stopped uploading cannot give a
    half complete release.

Files are found by file name, not by artifact name. The artifact names are
not uniform. linux.yml uploads the amd64 tarball and .deb under their file
names, but the arm and arm64 jobs put two files under one
linux-<goarch>-double-zipped-<version> name, and build-macos.yml does the
same. A search by file name handles both, and a later cleanup of those names
cannot break this workflow.

Release notes come from the CHANGELOG.md entry for that version, through the
new .github/workflows/extract-changelog.sh. The release is a draft, so the
notes can be reviewed before publication. The title is the bare version, which
matches every release from 0.27.0 to 0.41.1.

No checksum file. GitHub keeps a SHA-256 digest of every asset. BUILDING.md
gives the command that prints them.

BUILDING.md gets a "Publish a release" section with the full procedure.

Tested

Local:

  • sh -n on the script, bash -n on every run block, and a YAML parse.
  • extract-changelog.sh against the newest entry, a middle entry, the oldest
    entry (the end of file case) and an unknown version.
  • The collect step against a directory tree that copies the real artifact
    names, for the complete case and for a missing file.
  • The version check for the -dev, wrong tag and correct tag cases.

Still to do, because it cannot run locally: an end to end run on a fork, and the
two negative cases.

Follow-up

linux.yml:465, linux.yml:471 and build-macos.yml:106 still use the
*-double-zipped-* names. No download-artifact step reads them, so a rename
is safe, but it belongs in its own PR.

@deadprogram deadprogram changed the title ci: publish a draft release from the artifacts that CI already built ci: publish draft release from the pre-built CI artifacts Aug 29, 2026
@deadprogram deadprogram changed the title ci: publish draft release from the pre-built CI artifacts ci: publish draft releases from pre-built CI artifacts Aug 29, 2026
@deadprogram deadprogram changed the title ci: publish draft releases from pre-built CI artifacts ci: publish releases from pre-built CI artifacts Aug 29, 2026
@github-actions

Copy link
Copy Markdown

Size difference with the dev branch:

Binary size difference
 flash                          ram
 before   after   diff          before   after   diff
  19684   19684      0   0.00%    7052    7052      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/adafruit4650
  63228   63228      0   0.00%    6788    6788      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adt7410/main.go
  10024   10024      0   0.00%    5348    5348      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go
  14628   14628      0   0.00%    7396    7396      0   0.00% tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/amg88xx
  10184   10184      0   0.00%    5348    5348      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go
  12592   12592      0   0.00%    7172    7172      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/apds9960/proximity/main.go
  11136   11136      0   0.00%    5360    5360      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
   7588    7588      0   0.00%    2312    2312      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go
   9272    9272      0   0.00%    5340    5340      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bh1750/main.go
   8660    8660      0   0.00%    5340    5340      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/blinkm/main.go
  71408   71408      0   0.00%    3656    3656      0   0.00% tinygo build -size short -o ./build/test.hex -target=pinetime     ./examples/bma42x/main.go
  67120   67120      0   0.00%    6804    6804      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmi160/main.go
  28952   28952      0   0.00%    5380    5380      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp180/main.go
  65720   65720      0   0.00%    6828    6828      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp280/main.go
  13080   13080      0   0.00%    5412    5412      0   0.00% tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bmp388/main.go
  24024   24024      0   0.00%    6220    6220      0   0.00% tinygo build -size short -o ./build/test.hex -target=metro-rp2350 ./examples/bno08x/i2c/main.go
   8008    8008      0   0.00%    3344    3344      0   0.00% tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
  22116   22116      0   0.00%    3548    3548      0   0.00% tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
  30556   30556      0   0.00%    5576    5576      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/alarms/main.go
  44492   44492      0   0.00%    5576    5576      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/basic/main.go
   4592    4592      0   0.00%    2272    2272      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
  71884   71884      0   0.00%    7588    7588      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/flash/console/spi
  67996   67996      0   0.00%    9628    9628      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/flash/console/qspi
   7128    7128      0   0.00%    2276    2276      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/gc9a01/main.go
 694072  694072      0   0.00%  131564  131564      0   0.00%

The Linux, macOS and Windows workflows build every file that a release
needs when the release branch is pushed. The new Release workflow finds
those runs for the tagged commit, waits for them, and collects their nine
files into a draft release. It builds nothing, so what ships is what was
tested.

The release notes come from the CHANGELOG.md entry for that version.

Signed-off-by: Ron Evans <ron@hybridgroup.com>
@deadprogram

Copy link
Copy Markdown
Member Author

Currently testing this in a fork...

@deadprogram

Copy link
Copy Markdown
Member Author

Tested end to end on a fork, https://github.com/deadprogram/tinygo.

The first attempt found a real bug. gh run download always tries to unpack the
artifact as a zip, but the build jobs upload with archive: false, so the
artifact is the release file itself:

error downloading tinygo_0.42.0_amd64.deb: error extracting zip archive: zip: not a valid zip file

The workflow now uses actions/download-artifact@v8 with run-id,
github-token and skip-decompress: true, one step per build workflow, and
permissions gained actions: read. The wait step gives the three run ids as
separate outputs. Force pushed.

With that fix, a stub run that produces the nine correctly named files passed
completely: https://github.com/deadprogram/tinygo/actions/runs/33246333604

  • The workflow found the three runs and waited for them.
  • The draft release has the nine assets, the title 0.42.0, and the
    CHANGELOG.md entry as its body.
  • The assets are the raw files. The Windows .zip is not unpacked.
  • go-mod-tidy on the ubuntu-slim label schedules on a fork.

Negative cases:

  • Tag v9.9.9 against version 0.42.0 fails at "Read the version" with
    tag v9.9.9 does not match version 0.42.0 in goenv/version.go, and creates no
    release.
  • A tag on a commit that CI never built polls for 10 minutes, then fails with
    no linux.yml run for commit <sha>, and creates no release.

The run with the real builds is in progress. I will report the result.

@deadprogram

Copy link
Copy Markdown
Member Author

The run with the real builds passed.

Fork run: https://github.com/deadprogram/tinygo/actions/runs/33247041566

The Linux, macOS and Windows workflows all concluded success on the tagged
commit, the release workflow waited for them, and the draft release for
v0.42.1 holds the nine real files, with the title 0.42.1 and the
CHANGELOG.md entry as its body.

Every published asset digest equals the digest of the artifact its build job
produced:

sha256:75a9bc5be58db4609946ae7111bc8ca26ee174b6a3ae2f59256b6497a42d0ca6  tinygo0.42.1.linux-amd64.tar.gz
sha256:8bc6a532d09854e8a9811c21995d9f38f2e9d98b71a7c77fede7f783dad038db  tinygo0.42.1.linux-arm.tar.gz
sha256:1d70e02e9d1a306f1e8b2001ec737e7858d68ba408e679ced19d226315131dab  tinygo0.42.1.linux-arm64.tar.gz
sha256:0c20d1e8b2a78bd8438cdd57a60973b8e8f44fe1ba3320a191f35708d71ae57e  tinygo0.42.1.darwin-amd64.tar.gz
sha256:8c50109a9c3e28aa87ce257accbc57d7ae0e522e1971276a8503944b88ee6df0  tinygo0.42.1.darwin-arm64.tar.gz
sha256:4d7bb1d23267eddba1e483a59c2326e7bc62ade299f3835bcc88cbf899c8dbdb  tinygo0.42.1.windows-amd64.zip
sha256:b3eeef5580b045e53b3b26b4219fef796cf578b67633a113748e48431fff7846  tinygo_0.42.1_amd64.deb
sha256:f5acadc4d1a801292aaeb0d003ff776b2ee5ab3511feaba26bab7914863c5674  tinygo_0.42.1_arm64.deb
sha256:a3a0f607e362510df8b9ddbc8e1c0113b3d8f67ee8d13976a80b844dc460202b  tinygo_0.42.1_armhf.deb

The Docker workflow failed on the fork, because it needs the Docker Hub
secrets, which a fork does not have. The release workflow is not affected: it
looks at linux.yml, build-macos.yml and windows.yml only. This is
incidental evidence that the gate is exactly those three workflows.

@deadprogram

Copy link
Copy Markdown
Member Author

Once #5627 is merged we can merge this one!

@deadprogram

Copy link
Copy Markdown
Member Author

#5627 has been merged so this is now ready!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant